<template>
  <view
    class="tm-segtab relative flex flex-col"
    :class="[`round-${props.round}`]"
    ref="tm-segtab"
    :style="{ width: wh.outerWidth + 'rpx', height: wh.outerHeight + 'rpx' }"
  >
    <tm-sheet
      :round="props.round"
      :linear="props.linear"
      :linear-deep="props.linearDeep"
      :no-level="true"
      :color="props.bgColor"
      darkBgColor="rgba(255,255,255,0.06)"
      :height="wh.outerHeight"
      _class="flex-row relative overflow flex-1"
      class="flex-1"
      :padding="[0]"
      :margin="[0]"
      :border="0"
    >
      <!-- #ifdef APP-NVUE -->
      <view
        v-if="_cId !== '' && leftWidth >= 0"
        ref="tmBgEl"
        class="relative flex flex-row"
        :style="[
          {
            width: leftWidth + 'px',
            height: wh.innerHeight + 'rpx',
            top: `${props.gutter}rpx`,
            left: '0px',
          },
        ]"
      >
        <tm-sheet
          :follow-dark="props.followDark"
          :round="props.round"
          class="flex-1"
          _class="flex-1"
          :color="props.color"
          :margin="[0]"
          :padding="[0]"
        ></tm-sheet>
      </view>
      <!-- #endif -->
      <!-- #ifndef APP-NVUE -->
      <view
        v-if="_cId !== ''"
        class="absloute flex flex-row bgbtnpos tm-segtab relative"
        :style="[
          {
            transform: 'translateX(' + (leftPos + wh.gutterpx) + 'px)',
            width: leftWidth + 'px',
            height: wh.innerHieghtWeb,
            top: `${props.gutter}rpx`,
            left: '0px',
          },
        ]"
      >
        <tm-sheet
          :follow-dark="props.followDark"
          :round="props.round"
          class="flex-1 flex flex-row"
          parenClass="flex-1"
          _class="flex-1 flex flex-row"
          :color="props.color"
          :margin="[0, 0]"
          :padding="[0, 0]"
          :border="0"
        ></tm-sheet>
      </view>
      <!-- #endif -->
      <view
        class="absolute flex flex-row flex-row-center-start tm-segtab"
        :style="{
          width: `${wh.innerWidth}rpx`,
          height: wh.innerHeight + 'rpx',
          padding: `${props.gutter}rpx`,
          top: props.gutter + 'rpx',
        }"
      >
        <view
          @click="itemClick(index, item.id)"
          :ref="'tab_'"
          :class="['tab' + index]"
          class="flex flex-row flex-row-center-center px-16 nowrap flex-1"
          v-for="(item, index) in _list"
          :style="{ margin: `${props.gutter}rpx 0` }"
          :key="index"
        >
          <tm-text
            _style="transition: color 0.3s;"
            :color="item.id === _cId ? props.activeColor : props.fontColor"
            :lineHeight="0"
            :font-size="props.fontSize"
            :userInteractionEnabled="false"
            :label="item.text"
          ></tm-text>
        </view>
      </view>
    </tm-sheet>
  </view>
</template>
<script lang="ts" setup>
  /**
   * 分段器选项卡
   */
  import {
    computed,
    PropType,
    toRaw,
    getCurrentInstance,
    ref,
    onMounted,
    nextTick,
    watch,
    Ref,
    inject,
  } from 'vue';
  import tmSheet from '../tm-sheet/tm-sheet.vue';
  import tmText from '../tm-text/tm-text.vue';
  import { listitem } from './interface';
  import { custom_props } from '../../tool/lib/minxs';
  // #ifdef APP-PLUS-NVUE
  const dom = uni.requireNativePlugin('dom');
  const animation = uni.requireNativePlugin('animation');
  // #endif
  const proxy = getCurrentInstance()?.proxy ?? null;
  const emits = defineEmits(['update:modelValue', 'change', 'click']);

  const props = defineProps({
    ...custom_props,
    round: {
      type: Number,
      default: 2,
    },
    width: {
      type: Number,
      default: 600,
    },
    height: {
      type: Number,
      default: 64,
    },
    gutter: {
      type: Number,
      default: 4,
    },
    list: {
      type: Array as PropType<Array<string | listitem>>,
      default: () => [],
      required: true,
    },
    //v-model可以是index索引也可是对象id
    modelValue: {
      type: [Number, String],
      default: 0,
    },
    //如果想以字段id来达到index选中效果。需要list为对象，并且提供唯一标识id字段。
    defaultValue: {
      type: [Number, String],
      default: 0,
    },
    //在点击切换之前执行，返回false阻止切换，可以是Promise
    beforeChange: {
      type: [Function, Boolean],
      default: () => false,
    },
    color: {
      type: String,
      default: 'white',
    },
    fontColor: {
      type: String,
      default: '#000000',
    },
    bgColor: {
      type: String,
      default: 'grey-3',
    },
    fontSize: {
      type: Number,
      default: 24,
    },
    //被选中后的文字色
    activeColor: {
      type: String,
      default: 'primary',
    },
    disable: {
      type: Boolean,
      default: false,
    },
  });
  const leftPos = ref(-100);
  const leftWidth = ref(0);
  let timid: any = uni.$tm.u.getUid();
  const _list = computed(() => {
    let templist = [];
    for (let i = 0, len = props.list.length; i < len; i++) {
      let al: listitem = { text: '', id: i };
      let el = props.list[i];
      if (typeof el == 'string' || typeof el == 'number') {
        al.text = el;
      } else if (typeof el == 'object') {
        al.text = el?.text ?? '';

        if (typeof el?.id != 'undefined') {
          al.id = el['id'];
        }
      }
      templist.push(al);
    }

    return templist;
  });
  const firstRender = ref(true);
  //当前值。
  const _cId: Ref<string | number> = ref(props.defaultValue ?? 0);
  const _blackValue = _cId.value;
  //如果list提供的是对象，想以id来选中定位，而不是inde索引则需要转换。
  function zhunhuanid(val: string | number) {
    let index = _list.value.findIndex((el) => el.id == val);
    return index;
  }
  // 外框宽度
  const wh = computed(() => {
    let iw = props.width - props.gutter;
    // #ifdef APP-NVUE
    iw = props.width;
    // #endif
    // console.log((uni.upx2px(props.height)-uni.upx2px(props.height - props.gutter * 2))/2,uni.upx2px(props.gutter))
    let inheight = '';
    // #ifndef APP-NVUE
    inheight = `calc(100% - ${props.gutter * 2}rpx)`;
    // #endif
    return {
      outerWidth: props.width,
      outerHeight: props.height,
      innerWidth: iw,
      innerHeight: props.height - props.gutter * 2,
      innerHieghtWeb: inheight,
      gutterpx: (uni.upx2px(props.height) - uni.upx2px(props.height - props.gutter * 2)) / 2,
    };
  });

  async function itemClick(index: number, id: number | string) {
    emits('click', index);
    if (props.disable) {
      return;
    }
    if (typeof props.beforeChange === 'function') {
      uni.showLoading({ title: '...', mask: true });
      let p = await props.beforeChange(index);
      if (typeof p === 'function') {
        p = await p(index);
      }
      uni.hideLoading();
      if (!p) return;
    }
    if (_cId.value === id) return;
    _cId.value = id;
    getDomRectBound(index);
    emits('change', _cId.value, toRaw(_list.value[index]));
    emits('update:modelValue', _cId.value);
    initPos();
  }
  watch(
    [() => props.list],
    () => {
      initPos();
    },
    { deep: true },
  );
  watch([() => props.modelValue], () => {
    if (_cId.value == props.modelValue) return;
    _cId.value = props.modelValue;
    initPos();
  });
  onMounted(() => {
    initPos();
  });
  //定位背景按钮位置。
  function initPos() {
    let indexel = _list.value.findIndex((el) => el.id === _cId.value);
    clearTimeout(timid);
    let timerdur = 150;
    // #ifndef APP-NVUE
    timerdur = 50;
    // #endif

    timid = setTimeout(() => {
      nextTick(() => getDomRectBound(indexel));
    }, timerdur);
  }
  function getEl(el) {
    if (typeof el === 'string' || typeof el === 'number') return el;
    if (WXEnvironment) {
      return el.ref;
    } else {
      return el instanceof HTMLElement ? el : el.$el;
    }
  }
  function getDomRectBound(idx: number) {
    // #ifdef APP-NVUE
    dom.getComponentRect(proxy?.$refs['tm-segtab'], function (PARENAREDS) {
      if (PARENAREDS?.size) {
        let parentleft = Math.floor(PARENAREDS.size.left ?? 0);
        dom.getComponentRect(proxy?.$refs['tab_'][idx], function (res) {
          if (res?.size) {
            const { left, top, width } = res.size;
            let domx = getEl(proxy?.$refs['tmBgEl']);
            leftWidth.value = Math.ceil(width ?? 0);
            leftPos.value = Math.ceil((left ?? 0) - uni.upx2px(props.gutter) - parentleft);
            animation.transition(
              proxy?.$refs['tmBgEl'],
              {
                styles: {
                  transform: 'translateX(' + (leftPos.value + wh.value.gutterpx) + 'px)',
                },
                duration: firstRender.value ? 1 : 200, //ms
                timingFunction: 'ease',
                delay: 0, //ms
              },
              () => {
                firstRender.value = false;
              },
            );
          }
        });
      }
    });
    // #endif
    // #ifndef APP-NVUE
    uni
      .createSelectorQuery()
      .in(proxy)
      .select('.tm-segtab')
      .boundingClientRect((nodeParent) => {
        let parentleft = nodeParent?.left ?? 0;
        uni
          .createSelectorQuery()
          .in(proxy)
          .select('.tab' + idx)
          .boundingClientRect((node) => {
            if (!node) return;
            leftPos.value = (node?.left ?? 0) - uni.upx2px(props.gutter) - parentleft;
            leftWidth.value = (node?.width ?? 0) + +uni.upx2px(props.gutter);
          })
          .exec();
      })
      .exec();
    // #endif
  }
</script>
<style scoped>
  .bgbtnpos {
    transition-timing-function: cubic-bezier(0.18, 0.89, 0.32, 1);
    transition-duration: 0.4s;
    transition-property: left, width, transform;
    transition-delay: 0s;
  }
  .tm-segtab {
    display: flex;
    /* #ifndef APP-NVUE */
    box-sizing: border-box;
    /* #endif */
  }
</style>
